import { Component, _decorator, SpriteComponent, Node, EventTouch, geometry, Vec2, v2, Quat, toDegree, Vec3 } from "cc";
const { ccclass, property } = _decorator;
import { OTWSceneManager } from "./OTWSceneManager";

@ccclass('OTWGameTouchController')
export class OTWGameTouchController extends Component {
    @property({ type: Node, tooltip: "捕获游戏手势操作的节点,尽量全屏的节点,但要放在UI节点之下" })
    public GameTouchCaption!: Node;

    @property({ type: SpriteComponent, tooltip: "攻击选择来源" })
    public AttackFrom!: SpriteComponent;
    @property({ type: SpriteComponent, tooltip: "攻击选择目标" })
    public AttackTo!: SpriteComponent;
    @property({ type: SpriteComponent, tooltip: "攻击选择箭头" })
    public AttackArrow!: SpriteComponent;

    public sceneMgr!: OTWSceneManager;
    public touchRayGetObjHandler?: (isFrom: boolean, ray: geometry.Ray) => any;
    public touchFromToHandler?: (fromNode: any, toNod: any) => void;


    tmpRay: geometry.Ray = new geometry.Ray();
    fromNode: any = null;
    toNode: any = null;
    /**箭头默认的朝向*/
    arrowDefDir: Vec2 = v2(1, 0);
    /**箭头临时朝向*/
    arrowTmpDir: Vec2 = v2(0, 0);
    arrowQuat: Quat = new Quat();
    arrowScale: Vec3 = new Vec3(1, 1, 1);

    start() {
        this.GameTouchCaption?.on(Node.EventType.TOUCH_START, this.onGameTouchStart, this);
        this.GameTouchCaption?.on(Node.EventType.TOUCH_MOVE, this.onGameTouchMove, this);
        this.GameTouchCaption?.on(Node.EventType.TOUCH_END, this.onGameTouchEnd, this);
        this.GameTouchCaption?.on(Node.EventType.TOUCH_CANCEL, this.onGameTouchCancel, this);

        this.AttackFrom.node.setPosition(-999, -999, -999);
        this.AttackTo.node.setPosition(-999, -999, -999);
        this.AttackArrow.node.setPosition(-999, -999, -999);
    }

    onGameTouchStart(ev: EventTouch) {
        this.fromNode = null;
        this.AttackFrom.node.setPosition(-999, -999, -999);

        if (ev.getAllTouches().length > 1) {
            //两个手指操作就取消
            return;
        }
        const touch = ev.touch!;
        var uiX = touch.getUILocationX();
        var uiY = touch.getUILocationY();
        this.sceneMgr.MainCamera?.screenPointToRay(touch.getLocationX(), touch.getLocationY(), this.tmpRay);
        var node = this.touchRayGetObjHandler?.call(this, true, this.tmpRay);
        if (!node) return;

        this.fromNode = node;
        this.AttackFrom.node.setPosition(uiX, uiY, 0);

        this.AttackArrow.node.setPosition(uiX, uiY, 0);
        this.arrowScale.x = 1;
        this.AttackArrow.node.setScale(this.arrowScale);
    }
    onGameTouchMove(ev: EventTouch) {
        if (!this.fromNode) return;
        this.toNode = null;
        this.AttackTo.node.setPosition(-999, -999, -999);

        const touch = ev.touch!;
        var uiX = touch.getUILocationX();
        var uiY = touch.getUILocationY();
        var dirX = uiX - this.AttackArrow.node.position.x;
        var dirY = uiY - this.AttackArrow.node.position.y;
        if (dirX == 0 && dirY == 0) return;

        //更新箭头指向
        this.arrowTmpDir.x = dirX;
        this.arrowTmpDir.y = dirY;
        this.arrowTmpDir.normalize();
        var angle = this.arrowDefDir.signAngle(this.arrowTmpDir);
        Quat.fromAxisAngle(this.arrowQuat, Vec3.UNIT_Z, angle);
        this.AttackArrow.node.setRotation(this.arrowQuat);
        var dis = Math.sqrt(dirX * dirX + dirY * dirY);
        var mu = dis / 30;
        this.arrowScale.x = mu;
        this.AttackArrow.node.setScale(this.arrowScale);

        this.sceneMgr.MainCamera?.screenPointToRay(touch.getLocationX(), touch.getLocationY(), this.tmpRay);
        var node = this.touchRayGetObjHandler?.call(this, false, this.tmpRay);
        if (!node || node == this.fromNode) return;

        this.toNode = node;
        this.AttackTo.node.setPosition(uiX, uiY, 0);
    }
    onGameTouchEnd(ev: EventTouch) {
        if (!this.fromNode || !this.toNode) {
            this.onGameTouchCancel(ev);
            return;
        }
        var f = this.fromNode;
        var t = this.toNode;
        this.onGameTouchCancel(ev);
        this.touchFromToHandler?.call(this, f, t);
    }
    onGameTouchCancel(ev: EventTouch) {
        this.fromNode = null;
        this.AttackFrom.node.setPosition(-999, -999, -999);
        this.toNode = null;
        this.AttackTo.node.setPosition(-999, -999, -999);

        this.AttackArrow.node.setPosition(-999, -999, -999);
    }
}